<!DOCTYPE html>
<html lang="zh-cn">
<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>文件下载器</title>
</head>
<body>
  <button onclick="downLoad()" id='btn'>流式文件下载</button>
  <input id='input' type="file" hidden />
  <script type="text/javascript">
    const btn = document.getElementById('btn')
    const input = document.getElementById('input')
    async function downLoad() {
      const res = await fetch('./metavers.exe')
      const reader = res.body.getReader()
      const writableStream = await createDownloadStream('metavers.exe')
      const writable = writableStream.getWriter()

      const pump = async () => {
        const { done, value } = await reader.read()
        if (done) return writable.close()
        console.log('value--->', value)
        await writable.write(value)
        pump()
      }
       pump()
    }

    async function createDownloadStream(filename) {
      const { port1, port2 } = new MessageChannel()

      const sw = await register();

      sw.postMessage({ filename }, [port2]);

      return new Promise((resolve) => {
        port1.onmessage = (e) => {
          const iframe = document.createElement("iframe")
          iframe.hidden = true
          iframe.src = e.data.download
          iframe.name = "iframe"
          document.body.appendChild(iframe)
          resolve(e.data.writable)
        }
      })
    }

    async function register() {
      const registed = await navigator.serviceWorker.getRegistration("./")
      if (registed?.active) return registed.active

      const swRegistration = await navigator.serviceWorker.register("down.js", {
        scope: "./",
      })

      const sw = swRegistration.installing || swRegistration.waiting

      let listen

      return new Promise((resolve) => {
        sw.addEventListener(
          "statechange",
          (listen = () => {
            if (sw.state === "activated") {
              sw.removeEventListener("statechange", listen)
              resolve(swRegistration.active)
            }
          })
        )
      })
    }


    // if ('serviceWorker' in navigator) {
    //   window.addEventListener('load', () => {
    //     navigator.serviceWorker.register('./down.js', { scope: './' })
    //       .then(registration => {
    //         console.log('ServiceWorker registration successful with scope: ', registration.scope)
    //       })
    //       .catch(err => {
    //         console.log('ServiceWorker registration failed: ', err)
    //       })
    //   })
    // }
  </script>
</body>
</html>